package com.muyu.chat.websocket.server;

import com.muyu.common.core.exception.ServiceException;
import com.muyu.common.core.text.Convert;
import com.muyu.common.core.utils.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.util.Assert;

import javax.validation.constraints.NotNull;
import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: 聊天socket服务本地缓存
 * @author: MuYu
 * @date: 2024/10/12-11:55
 */
@Log4j2
public class ChatSessionLocalLocalOnline {

    private final static ChatSessionLocalLocalOnline instance;

    static {
        instance = new ChatSessionLocalLocalOnline();
    }

    public static ChatSessionLocalLocalOnline getInstance() {
        return instance;
    }

    private void ChatSessionLocalLocalOnline() {}


    /**
     * 用户和聊天session会话
     */
    private final static Map<Session, Long> sessionToUserMap = new ConcurrentHashMap<>();
    private final static Map<Long, Session> userToSessionMap = new ConcurrentHashMap<>();

    /**
     * 创建服务器
     * @param session 服务会话
     * @param userId 用户ID
     */
    public void storage(Session session, Long userId) {
        if (session == null){
            throw new ServiceException("session为空，创建失败");
        }
        if (userId == null){
            throw new ServiceException("userId为空，创建失败");
        }
        sessionToUserMap.put(session, userId);
        userToSessionMap.put(userId, session);
        log.info("创建socket服务会话：[userId:{},sessionId:{}]，当前在线数量：[{}位]", userId, session.getId(), onlineCount());
    }

    /**
     * 通过session销毁会话
     * @param session 服务会话
     */
    public void destroyBySession(@NotNull Session session) {
        if (session == null){
            throw new ServiceException("session为空");
        }
        Long userId = sessionToUserMap.remove(session);
        if (userId != null) {
            userToSessionMap.remove(userId);
        }
        log.info("删除socket服务会话：[userId:{},sessionId:{}]，当前在线数量：[{}位]", userId, session.getId(), onlineCount());
    }

    /**
     * 通过用户ID销毁会话
     * @param userId 用户ID
     */
    public void destroyByUserId(@NotNull String userId) {
        if (userId == null){
            throw new ServiceException("用户ID为空");
        }
        Session session = userToSessionMap.remove(userId);
        if (session != null) {
            sessionToUserMap.remove(session);
        }
        log.info("删除socket服务会话：[userId:{},sessionId:{}]，当前在线数量：[{}位]", userId, session.getId(), onlineCount());
    }


    /**
     * 在线用户信息
     * @return 在线用户
     */
    public int onlineCount(){
        return sessionToUserMap.size();
    }

    /**
     * 检查用户是否在线
     * @param session 会话
     */
    public void checkIsOnlineBySession(Session session) {
        Assert.isTrue(sessionToUserMap.containsKey(session), StringUtils.format("会话Session为空:{}",session.getId()));
    }

    /**
     * 检查用户是否在线
     * @param userId 用户ID
     */
    public void checkIsOnlineByUserId(String userId) {
        Assert.isTrue(userToSessionMap.containsKey(userId), StringUtils.format("会话不存在，用户ID：{}",userId));
    }

    /**
     * 用户是否在线
     * @param userId 用户ID
     * @return 在线为true
     */
    public boolean isOnlineByUserId(Long userId) {
        return userToSessionMap.containsKey(userId);
    }


    /**
     * 通过session发送消息
     * @param session 会话主体
     * @param message 消息体
     */
    public void sendBySession(Session session, String message) {
        if (session == null){
            throw new ServiceException("session为空，发送消息失败");
        }
        if (StringUtils.isBlank(message)){
            throw new ServiceException("消息体为空，无法进行消息发送");
        }
        RemoteEndpoint.Async asyncRemote = session.getAsyncRemote();
        asyncRemote.sendText(message);
        log.info("消息发送成功：[sessionId:{},userId:{},msg:{}]", session.getId(), sessionToUserMap.get(session), message);
    }

    /**
     * 通过UserId发送消息
     *
     * @param userId    用户ID
     * @param message   消息体
//     * @param receiveId
     */
    public void sendByUserId(Long userId, String message) {
        if (userId == null){
            throw new ServiceException("userId为空，发送消息失败");
        }
//        if (StringUtils.isBlank(message)){
//            throw new ServiceException("消息体为空，无法进行消息发送");
//        }
        Session session = userToSessionMap.get(userId);
        checkIsOnlineBySession(session);
        sendBySession(session, message);
    }

    public Long getUserIdBySession(Session session) {
        return Convert.toLong(sessionToUserMap.get(session), null);
    }
}
